﻿using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractMachineState;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.Devices;
using HamcoWcs.Service.Common;
using HamcoWcs.Models.Events;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HamcoWcs.Entitys.Devices;
using Microsoft.EntityFrameworkCore.Diagnostics;
using HamcoWcs.DAL;
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;

namespace HamcoWcs.Service.MachineStateService
{
    [AutoInject(typeof(IMachineStateService), InjectType.Single)]
    public class MachineStateService : IMachineStateService
    {
        private readonly IServiceScopeFactory _scopeFactory;
        private readonly IMapper _mapper;
        private readonly ILoggerService _logger;
        private ConcurrentDictionary<string, MachineStateMode> MachineStateDic = new ConcurrentDictionary<string, MachineStateMode>();
        private ConcurrentQueue<MachineState> MachineStateQueue = new ConcurrentQueue<MachineState>();
        public MachineStateService(IServiceScopeFactory scopeFactory, IMapper mapper, ILoggerService logger)
        {
            _mapper = mapper;
            _scopeFactory = scopeFactory;
            _logger = logger;
            InitData();
        }
        private void InitData() 
        {
            MachineStateMode.DevicesStateSaveEvent += OnSaveMachineState;
            Task.Run(() => 
            {
                while (true)
                {
                    DoSaveMachineState();
                }
            });
        }
        public void SaveMachineState(string machineName, EnumMachineState machineState)
        {
            Task.Run(() =>
            {
                if (MachineStateDic.ContainsKey(machineName))
                {
                    MachineStateDic[machineName].UpateData(machineState);
                }
                else
                {
                    var machine = new MachineStateMode(machineName);
                    machine.UpateData(machineState);
                    MachineStateDic.TryAdd(machineName, machine);
                }
            });
            
        }

        public void UnPublish()
        {
            MachineStateMode.DevicesStateSaveEvent -= OnSaveMachineState;
        }
        private void OnSaveMachineState(object sender, DevicesStateSaveEvent e)
        {
            MachineStateQueue.Enqueue(e.MachineState);
        }

        private void DoSaveMachineState()
        {
            try
            {
                if (MachineStateQueue.Count < 1) return;
                MachineState MachineState;
                MachineStateQueue.TryDequeue(out MachineState);
                if (MachineState != null)
                {
                    using (var scope = _scopeFactory.CreateScope())
                    {
                        var _wcsDbContext = scope.ServiceProvider.GetRequiredService<WcsDbContext>();
                        _wcsDbContext.Set<MachineState>().Add(MachineState);
                        _wcsDbContext.SaveChanges();
                    }
                    Thread.Sleep(100);
                }
            }
            catch (Exception e)
            {
                _logger.AddWcsRunLog("",$"DoSaveMachineState Error. ErrorMessage = {e.Message}");
            }
        }

    }
}
